package com.fubon.wloan.service;

import com.alibaba.fastjson.JSON;
import com.fubon.wloan.pojo.Body;
import com.fubon.wloan.pojo.Expanding;
import com.fubon.wloan.pojo.InvestInfo;
import com.fubon.wloan.pojo.InvestResp;
import com.fubon.wloan.pojo.InvestStatus;
import com.fubon.wloan.pojo.Resp;
import com.fubon.wloan.pojo.Trans;
import com.fubon.wloan.repository.InvestRepository;
import com.fubon.wloan.repository.InvestRespRepository;
import com.fubon.wloan.repository.InvestStatusRepository;
import com.fubon.wloan.util.CryptoUtil;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.web.reactive.function.client.WebClient;

import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;

import java.time.Duration;






@Service
public class InverstServiceImp implements InvestService {
    @Value("${forward.host}")
    private String host;

    @Value("${forward.url.InvestInfo}")
    private String urlInvestInfo;

    @Autowired
    private InvestRepository investRepository;

    @Autowired
    private InvestStatusRepository investStatusRepository;

    @Autowired
    private InvestRespRepository investRespRepository;
    

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    @Qualifier("jdbcScheduler")
    private Scheduler jdbcSecheduler;
    
    @Override
    public Mono<InvestStatus> SaveData(Body<InvestInfo,Expanding> body) {
        return Mono.defer(() -> transactionTemplate.execute(status -> {
            String personStr = JSON.toJSONString(body.getBasicInfo());
            InvestInfo investInfo = JSON.parseObject(personStr,InvestInfo.class);
            investInfo.setId(body.getReqSn());
            //InvestInfo acc = 
            investRepository.save(investInfo);

            InvestStatus is =new InvestStatus();
            is.setReqSn(body.getReqSn());
            is.setTimeStamp(body.getTimestamp());
            is.setStatus(0);
            InvestStatus investStatus = investStatusRepository.save(is);

            return Mono.just(investStatus);
        })).subscribeOn(jdbcSecheduler);   
    }

    @Override
    public Mono<Resp> SendCallbackMsg(Body<InvestInfo, Expanding> body){
        return Mono.defer(()->{
            Mono<InvestResp<Expanding>> resp =  WebClient.create(host)
            .post()
            .uri("http://localhost:8088/api/replytest")
            .accept(MediaType.APPLICATION_JSON)
            .bodyValue(body)
            .retrieve()
            .bodyToMono(InvestResp.class)
            .log()
            .map(httpResp -> investRespRepository.save(httpResp));
            resp.subscribe();
            
            Mono<Resp> callbackResp = WebClient.create(host)
                        .post()
                        .uri("http://localhost:8088/api/callback")
                        .accept(MediaType.APPLICATION_JSON)
                        .bodyValue(CryptoUtil.encode(Trans.builder().icode("xxxx").data(JSON.toJSONString(resp.block(Duration.ofSeconds(2)))).build()))
                        .retrieve()
                        .bodyToMono(Trans.class)
                        .map(callbackreturn -> JSON.parseObject(CryptoUtil.decode(callbackreturn).getData(),Resp.class))
                        .log();
            return callbackResp;
        }).subscribeOn(jdbcSecheduler);
        
    }

    @Override
    public Mono<InvestResp<Expanding>> findByReqSn(final String reqSn) {
        
        Mono<InvestResp<Expanding>> resp = Mono.defer(()-> Mono.just(investRespRepository.findByReqSn(reqSn))).subscribeOn(jdbcSecheduler);
        
        return resp;
    }
}